#include <nrk.h>
#include <include.h>
#include <ulib.h>
#include <stdio.h>
#include <avr/sleep.h>
#include <hal.h>
#include <rt_link.h>
#include <nrk_error.h>
//#include <sys/time.h>
#include <bmac.h>

#define MY_CHANNEL 17

#define MAX_MOLES  4

NRK_STK Stack1[NRK_APP_STACKSIZE];
NRK_STK Stack2[NRK_APP_STACKSIZE];
nrk_task_type Task_rx, Task_tx;
void TaskRX(void);
void TaskTX(void);

void nrk_create_taskset();

uint8_t tx_buf[RF_MAX_PAYLOAD_SIZE];
uint8_t rx_buf[RF_MAX_PAYLOAD_SIZE];

uint8_t *local_rx_buf;
uint8_t length;
uint8_t  rssi,slot;

uint16_t Rounds = 0;
uint32_t Score = 0, Penalty = 0;

nrk_time_t timestart;
nrk_time_t timeend;
nrk_time_t newtime;

uint8_t mole_res = 1;

char c;

int main ()
{
  uint16_t div;
  nrk_setup_ports();
  nrk_setup_uart(UART_BAUDRATE_115K2);
	
  nrk_kprintf( PSTR("Starting up...\r\n") );
	
  nrk_init();
	
  nrk_led_clr(0);
  nrk_led_clr(1);
  nrk_led_clr(2);
  nrk_led_clr(3);
	
  nrk_time_set(0,0);
	
	
  bmac_task_config();
	
  nrk_create_taskset ();
	
  nrk_start();
	
  return 0;
}


void TaskTX()
{
  uint8_t i,last_mole,m;
  uint8_t oldMole,newMole=0;
  uint8_t counter = 0;
  volatile nrk_time_t t;
  nrk_sig_t uart_rx_signal;
  nrk_sig_t tx_done_signal;
  uint8_t ret;
	
  printf( "TaskTX PID=%d\r\n",nrk_get_pid());
	
  nrk_led_set(RED_LED);
	
  bmac_init ( MY_CHANNEL ); //bmac init on channel 17
	
  bmac_rx_pkt_set_buffer (rx_buf, RF_MAX_PAYLOAD_SIZE);
	
  while(!bmac_started())  
    nrk_wait_until_next_period(); 
	
  tx_done_signal = bmac_get_tx_done_signal (); //get signal for tx done
  nrk_signal_register (tx_done_signal); //register the task to wait signal
	
  // Get the signal for UART RX
  uart_rx_signal=nrk_uart_rx_signal_get();
  // Register task to wait on signal
  nrk_signal_register( uart_rx_signal );
	
  // This shows you how to wait until a key is pressed to start
  nrk_kprintf( PSTR("Press 's' to start\r\n" ));
	
  do{
    if(nrk_uart_data_ready(NRK_DEFAULT_UART))
      c=getchar();
    else nrk_event_wait(SIG(uart_rx_signal));
  } while(c!='s');
	
	
  while( 1 ) {
    if(mole_res == 1){
      oldMole = newMole;
      while( oldMole == newMole )
	newMole = rand()%MAX_MOLES;
      printf("NewMole = %d\r\n", newMole);
			
      sprintf( tx_buf, "Master count is %d and new mole is %d and Round = %d",counter,newMole,Rounds);
      // PKT_DATA_START + length of string + 1 for null at end of string
      length=strlen(tx_buf)+1;
      bmac_tx_pkt_nonblocking( tx_buf, length );
      printf( "\nTX done\r\n");
      ret = nrk_event_wait (SIG(tx_done_signal));
      nrk_time_get(&timestart);
      nrk_led_toggle(BLUE_LED);
      mole_res = 0;
    }
		
    nrk_wait_until_next_period();
  }
	
}


void TaskRX()
{
  uint8_t i, val;
  nrk_sig_t uart_rx_signal;
  nrk_sig_t rx_signal;
  nrk_sig_mask_t my_sigs;
	
  nrk_time_t timeout;
	
  printf( "TaskRX PID=%d\r\n",nrk_get_pid());
	
  while(!bmac_started())  
    nrk_wait_until_next_period(); 
  // Get the signal for UART RX
  uart_rx_signal=nrk_uart_rx_signal_get();
  // Register task to wait on signal
  nrk_signal_register(uart_rx_signal);
	
  rx_signal = bmac_get_rx_pkt_signal ();
  nrk_signal_register (rx_signal);
	
  timeout.secs = 5;
  timeout.nano_secs = 0;
	
  while(1){
    if ( Rounds >= 10 ) {
      printf("\nGame Over!\nScore : %d/10,",Score);
			
      nrk_kprintf( PSTR("Continue? (y/n)\r\n" ));
      do{
	if(nrk_uart_data_ready(NRK_DEFAULT_UART))
	  c=getchar();
	else nrk_event_wait(SIG(uart_rx_signal));
      } while(c!='y');
			
      Rounds = 0;
      Score = 0;
      mole_res = 1;
			
			
    }
    else {
      if(mole_res == 0){
	if(!bmac_rx_pkt_ready()){
	  val = bmac_wait_until_rx_pkt();
	}
	nrk_time_get(&newtime);
	local_rx_buf=bmac_rx_pkt_get(&length, &rssi);
				
	// print the packet out
	for(i=0; i<length; i++ )
	  printf( "%c",local_rx_buf[i] );
				
	if( (local_rx_buf[16]=='1') ) {
	  Score+= newtime.secs - timestart.secs;
	}
	bmac_rx_pkt_release();
	printf("Score : %d/", Score);
	printf("%d\r\n", Rounds);
	mole_res = 1;
	Rounds++;
      }
    }
    nrk_wait_until_next_period();	
  }
	
	
	
}

void nrk_create_taskset()
{
  Task_tx.task = TaskTX;
  Task_tx.Ptos = (void *) &Stack1[NRK_APP_STACKSIZE-1];
  Task_tx.Pbos = (void *) &Stack1[0];
  Task_tx.prio = 3;
  Task_tx.FirstActivation = TRUE;
  Task_tx.Type = BASIC_TASK;
  Task_tx.SchType = PREEMPTIVE;
  Task_tx.period.secs = 1;
  Task_tx.period.nano_secs = 0;
  Task_tx.cpu_reserve.secs = 0;
  Task_tx.cpu_reserve.nano_secs =  500*NANOS_PER_MS;
  Task_tx.offset.secs = 0;
  Task_tx.offset.nano_secs= 0;
  nrk_activate_task (&Task_tx);
	
  Task_rx.task = TaskRX;
  Task_rx.Ptos = (void *) &Stack2[NRK_APP_STACKSIZE-1];
  Task_rx.Pbos = (void *) &Stack2[0];
  Task_rx.prio = 2;
  Task_rx.FirstActivation = TRUE;
  Task_rx.Type = BASIC_TASK;
  Task_rx.SchType = PREEMPTIVE;
  Task_rx.period.secs = 1;
  Task_rx.period.nano_secs = 0;
  Task_rx.cpu_reserve.secs = 0;
  Task_rx.cpu_reserve.nano_secs = 500*NANOS_PER_MS;
  Task_rx.offset.secs = 0;
  Task_rx.offset.nano_secs= 0;
  nrk_activate_task (&Task_rx);
	
  nrk_kprintf( PSTR("Create Done\r\n") );
}
